/*============================================================================
 PROJECT: Halalgems
 FILE:    BaseNetwork.m
 AUTHOR:  Nguyen Quang Khai
 =============================================================================*/

/*============================================================================
 IMPORT
 =============================================================================*/

#import "BaseNetwork.h"
/*============================================================================
 MACRO
 =============================================================================*/

/*============================================================================
 PRIVATE INTERFACE
 =============================================================================*/
/*----------------------------------------------------------------------------
 Interface:   BaseNetwork
 -----------------------------------------------------------------------------*/
@interface BaseNetwork ()

@end

@implementation BaseNetwork
@synthesize networkEngine;
@synthesize enableDebugLog;

/*----------------------------------------------------------------------------
 Method:      init
 init function
 -----------------------------------------------------------------------------*/
- (id)init {
    self = [super init];
    if (self) {
    }
    
    return self;
}

- (id)initWithBaseURL:(NSString *)baseUrlString {
    self = [super init];
    if (self) {
        self.networkEngine = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:baseUrlString]];
        self.networkEngine.parameterEncoding = AFJSONParameterEncoding;
        [self configureRequestHeaderWithUser:nil];
    }
    
    return self;
    
}

/*----------------------------------------------------------------------------
 Method: service
 called to return a new service.
 -----------------------------------------------------------------------------*/
+ (BaseNetwork *)service {
    static BaseNetwork *shareService = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        if(!shareService) {
            shareService = [[BaseNetwork alloc] initWithBaseURL:kBaseService];
            
        }
    });
    return shareService;
}

/*----------------------------------------------------------------------------
 Method: configureRequestHeaderWithUser
 Set some default keys with their values to request header
 -----------------------------------------------------------------------------*/
- (void)configureRequestHeaderWithUser:(id)user {
    [networkEngine setDefaultHeader:kHTTP_HEADER_API_TOKEN value:kAPIKey];
    //    [networkEngine setDefaultHeader:kHTTP_HEADER_USER_TOKEN value:user.accessToken];
    //    [networkEngine setDefaultHeader:kHTTP_HEADER_USER_INFO value:user.userId];
    //    [networkEngine setDefaultHeader:kHTTP_HEADER_USER_LANG value:user.accessToken];
    //    [networkEngine setDefaultHeader:kHTTP_HEADER_APP_ID value:[[AppHelper sharedAppHelper] appId]];
    //    [networkEngine setDefaultHeader:kHTTP_HEADER_APP_VERSION value:[[AppHelper sharedAppHelper] appVersion]];
    //    [networkEngine setDefaultHeader:kHTTP_HEADER_APP_PIXEL_RATIO value:[[UIDevice currentDevice] resolutionToString]];
    //    [networkEngine setDefaultHeader:kHTTP_HEADER_APP_DEVICE_ACCESS value:@"Device Access"];
    //    [networkEngine setDefaultHeader:kHTTP_HEADER_TIME_ZONE value:[NSTimeZone localTimeZone].name];
    //    [networkEngine setDefaultHeader:@"Accept-Encoding" value:@"gzip"];
}
-(NSDictionary *) nestedDictionaryByReplacingNullsWithNil:(NSDictionary*)sourceDictionary
{
    NSMutableDictionary *replaced = [NSMutableDictionary dictionaryWithDictionary:sourceDictionary];
    const id nul = [NSNull null];
    const NSString *blank = @"";
    [sourceDictionary enumerateKeysAndObjectsUsingBlock:^(id key, id object, BOOL *stop) {
        //get object from dictionary
        object = [sourceDictionary objectForKey:key];
        //check object is null
        if([object isKindOfClass:[NSDictionary class]])
        {
            
            NSDictionary *innerDict = object;
            [replaced setObject:[self nestedDictionaryByReplacingNullsWithNil:innerDict] forKey:key];
            
        }
        else if([object isKindOfClass:[NSArray class]]){
            NSMutableArray *nullFreeRecords = [NSMutableArray array];
            for (id record in object) {
                
                if([record isKindOfClass:[NSDictionary class]])
                {
                    NSDictionary *nullFreeRecord = [self nestedDictionaryByReplacingNullsWithNil:record];
                    [nullFreeRecords addObject:nullFreeRecord];
                }
            }
            [replaced setObject:nullFreeRecords forKey:key];
        }
        else
        {
            if(object == nul) {
                [replaced setObject:blank forKey:key];
            }
        }
    }];
    
    return [NSDictionary dictionaryWithDictionary:replaced];
}
/*----------------------------------------------------------------------------
 Method: requestWithURL: params: successBlock: errorBlock: httpMethod:
 called to get data with path and params.
 -----------------------------------------------------------------------------*/
- (void)requestWithURL:(NSString *)inputUrlString
                params:(NSMutableDictionary *)params
          successBlock:(void (^)(id))successBlock
            errorBlock:(void (^)(NSString *))errorBlock
            httpMethod:(NSString *)method {
    
    if (!appDelegate.hasNetwork) {
        [NLUtils showAlertWithMessage:kNoConnectionErrorMessage];
        errorBlock(kNoConnectionErrorMessage);
        return;
    }
    //    if (appDelegate.dataCenter.onlineUserFond.accessToken) {
    //        [networkEngine setDefaultHeader:kHTTP_HEADER_APP_TOKEN value:appDelegate.dataCenter.onlineUserFond.accessToken];
    //
    //    }
    
    if ([method isEqualToString:@"GET"]) {
        [self.networkEngine getPath:inputUrlString
                         parameters:params
                            success:^(AFHTTPRequestOperation *operation, id jsonResponse) {
                                /* get URL string */
                                NSString *urlString = operation.request.URL.absoluteString;
                                DLog(@"Response for:%@\n\n%@==================", urlString, operation.responseString);
                                
                                NSDictionary *response = [self nestedDictionaryByReplacingNullsWithNil:[operation.responseString JSONValue]];
                                if (response) {
                                    successBlock(response);
                                } else {
                                    successBlock(operation.responseString);
                                }
                            }
                            failure:^(AFHTTPRequestOperation *operation, NSError *error) {
                                NSString *errorMessage = operation.responseString;
                                if (!errorMessage) {
                                    errorMessage = kServiceNotAvailableMessage;
                                }
                                /* get URL string */
                                NSString *urlString = operation.request.URL.absoluteString;
                                DLog(@"Response for:%@\n\n%@==================", urlString, operation.responseString);
                                errorBlock(errorMessage);
                            }];
    }
    else if ([method isEqualToString:@"PUT"]) {
        [self.networkEngine putPath:inputUrlString
                         parameters:params
                            success:^(AFHTTPRequestOperation *operation, id jsonResponse) {
                                NSDictionary *response = [operation.responseString JSONValue];
                                if (response) {
                                    successBlock(response);
                                } else {
                                    successBlock(operation.responseString);
                                }
                            }
                            failure:^(AFHTTPRequestOperation *operation, NSError *error) {
                                /* get URL string */
                                NSString *urlString = operation.request.URL.absoluteString;
                                DLog(@"Response for:%@\n\n%@==================", urlString, operation.responseString);
                                NSString *errorMessage = operation.responseString;
                                if (!errorMessage) {
                                    errorMessage = kServiceNotAvailableMessage;
                                }
                                errorBlock(errorMessage);
                            }];
    }
    else if ([method isEqualToString:@"POST"]) {
        [self.networkEngine postPath:inputUrlString
                          parameters:params
                             success:^(AFHTTPRequestOperation *operation, id jsonResponse) {
                                 NSDictionary *response = [self nestedDictionaryByReplacingNullsWithNil:[operation.responseString JSONValue]];
                                 if (response) {
                                     successBlock(response);
                                 } else {
                                     successBlock(operation.responseString);
                                 }
                             }
                             failure:^(AFHTTPRequestOperation *operation, NSError *error) {
                                 /* get URL string */
                                 NSString *urlString = operation.request.URL.absoluteString;
                                 DLog(@"Response for:%@\n\n%@==================", urlString, operation.responseString);
                                 NSString *errorMessage = operation.responseString;
                                 if (!errorMessage) {
                                     errorMessage = kServiceNotAvailableMessage;
                                 }
                                 errorBlock(errorMessage);
                             }];
    }
    else if ([method isEqualToString:@"DELETE"]) {
        [self.networkEngine deletePath:inputUrlString
                            parameters:params
                               success:^(AFHTTPRequestOperation *operation, id jsonResponse) {
                                   NSDictionary *response = [operation.responseString JSONValue];
                                   if (response) {
                                       successBlock(response);
                                   } else {
                                       successBlock(operation.responseString);
                                   }
                               }
                               failure:^(AFHTTPRequestOperation *operation, NSError *error) {
                                   /* get URL string */
                                   NSString *urlString = operation.request.URL.absoluteString;
                                   DLog(@"Response for:%@\n\n%@==================", urlString, operation.responseString);
                                   NSString *errorMessage = operation.responseString;
                                   if (!errorMessage) {
                                       errorMessage = kServiceNotAvailableMessage;
                                   }
                                   errorBlock(errorMessage);
                               }];
    }
}

/*----------------------------------------------------------------------------
 Method: requestWithHttpBody: headerFields: successBlock: errorBlock: httpMethod:
 called a request in SOAP type
 -----------------------------------------------------------------------------*/
- (void)requestWithHttpBody:(NSString *)httpBody
               headerFields:(NSMutableDictionary *)fields
               successBlock:(void (^)(id))successBlock
                 errorBlock:(void (^)(NSString *))errorBlock
                 httpMethod:(NSString *)method {
    
    if (!appDelegate.hasNetwork) {
        [NLUtils showAlertWithMessage:kNoConnectionErrorMessage];
        errorBlock(kNoConnectionErrorMessage);
        return;
    }
    
    /* create request */
    NSString *length = [NSString stringWithFormat:@"%d", httpBody.length];
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:kBaseService]];
    [request addValue:@"text/xml; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
    [request addValue:length forHTTPHeaderField:@"Content-Length"];
    
    /* additional fields */
    for (NSString *key in fields.allKeys) {
        [request addValue:[fields valueForKey:key] forHTTPHeaderField:key];
    }
    
    [request setHTTPMethod:method];
    [request setHTTPBody:[httpBody dataUsingEncoding:NSUTF8StringEncoding]];
    
    /* add to queue */
    AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
    
    [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
        if (enableDebugLog) {
            /* get URL string */
            NSString *urlString = operation.request.URL.absoluteString;
            
            /* check dict respone */
            DLog(@"Response for:%@\n==================\n%@==================", urlString, operation.responseString);
        }
        successBlock(responseObject);
    }                                failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        NSString *errorMessage = operation.responseString;
        if (!errorMessage) {
            errorMessage = kServiceNotAvailableMessage;
        }
        errorBlock(errorMessage);
    }];
    
    [networkEngine enqueueHTTPRequestOperation:operation];
}

- (void)dataForPath:(NSString *)filePath name:(NSString *)name result:(void (^)(NSData *data))result {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        if ([filePath hasPrefix:kAssetURLFormat]) {
            AssetLibraryHelper *library = [AssetLibraryHelper sharedPhotoLibraryAccessor];
            [library getAssestByURL:filePath
                        resultBlock:^(ALAsset *asset, NSError *error) {
                            NSData *data = nil;
                            if (!error) {
                                
                                /* get image correctly */
                                //                                UIImage *image = [asset originalImage];
                                
                                /* get expected size */
                                CGSize size;
                                if ([name isEqualToString:kAvatarUploadName]) {
                                    size = kExpectedAvatarSize;
                                } else {
                                    size = kExpectedPhotoSize;
                                }
                                // image = [image cropImageScaledToSize:size];
                                // data = [NLUtils compressImage:image toSize:size];
                            }
                            result(data);
                        }];
        } else {
            if (filePath.length > 0) {
                result([NSData dataWithContentsOfFile:filePath]);
            } else {
                result(nil);
            }
        }
    });
}
/*----------------------------------------------------------------------------
 Method: formRequestWithURLPath: params: filePath: successBlock: errorBlock: httpMethod:
 called a form request in SOAP type
 -----------------------------------------------------------------------------*/
- (void)formRequestWithURLPath:(NSString *)urlString
                        params:(NSMutableDictionary *)params
                      filePath:(NSData *)photo
                      filePath:(NSData *)video
                          name:(NSString *)name
                  successBlock:(void (^)(id))successBlock
                    errorBlock:(void (^)(NSString *))errorBlock {
    
    //    if (appDelegate.dataCenter.onlineUserFond.accessToken) {
    //        [networkEngine setDefaultHeader:kHTTP_HEADER_APP_TOKEN value:appDelegate.dataCenter.onlineUserFond.accessToken];
    //    }

    if (!appDelegate.hasNetwork) {
        [NLUtils showAlertWithMessage:kNoConnectionErrorMessage];
        errorBlock(kNoConnectionErrorMessage);
        return;
    }
    dispatch_async(dispatch_get_main_queue(), ^{
        
        NSMutableURLRequest *request =
        [networkEngine multipartFormRequestWithMethod:@"POST"
                                                 path:urlString
                                           parameters:params
                            constructingBodyWithBlock:^(id <AFMultipartFormData> formData) {
                                
                                if ([name isEqualToString:@"photo_file"]) {
                                    [formData appendPartWithFileData:photo
                                                                name:name
                                                            fileName:@"rah.jpeg"
                                                            mimeType:@"image/jpeg"];
                                } else {
                                    [formData appendPartWithFileData:photo
                                                                name:@"photo_file"
                                                            fileName:@"rah.jpeg"
                                                            mimeType:@"image/jpeg"];
                                    
                                    [formData appendPartWithFileData:video
                                                                name:@"video_file"
                                                            fileName:@"rah.mov"
                                                            mimeType:@"video"];
                                    
                                }
                            }];
        
        AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
        
        // if you want progress updates as it's uploading, uncomment the following:
        [operation setUploadProgressBlock:^(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite) {
            DLog(@"Sent %lld of %lld bytes", totalBytesWritten, totalBytesExpectedToWrite);
        }];
        
        [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
            if (enableDebugLog) {
                /* get URL string */
                NSString *urlString = operation.request.URL.absoluteString;
                
                /* check dict respone */
                DLog(@"Response for:%@\n==================\n%@==================", urlString, operation.responseString);
            }
            successBlock([operation.responseString JSONValue]);
        }                                failure:^(AFHTTPRequestOperation *operation, NSError *error) {
            NSString *errorMessage = error.localizedDescription;
            errorBlock(errorMessage);
        }];
        
        [networkEngine enqueueHTTPRequestOperation:operation];
    });
}
/*----------------------------------------------------------------------------
 Method: formRequestWithURLPath: params: filePath: successBlock: errorBlock: httpMethod:
 called a form request in SOAP type
 -----------------------------------------------------------------------------*/
- (void)formRequestWithURLPath:(NSString *)urlString
                        params:(NSMutableDictionary *)params
                      filePath:(NSData *)data
                          name:(NSString *)name
                  successBlock:(void (^)(id))successBlock
                    errorBlock:(void (^)(NSString *))errorBlock {
    
    //    if (appDelegate.dataCenter.onlineUserFond.accessToken) {
    //        [networkEngine setDefaultHeader:kHTTP_HEADER_APP_TOKEN value:appDelegate.dataCenter.onlineUserFond.accessToken];
    //    }

    if (!appDelegate.hasNetwork) {
        [NLUtils showAlertWithMessage:kNoConnectionErrorMessage];
        errorBlock(kNoConnectionErrorMessage);
        return;
    }
    dispatch_async(dispatch_get_main_queue(), ^{
        
        NSMutableURLRequest *request =
        [networkEngine multipartFormRequestWithMethod:@"POST"
                                                 path:urlString
                                           parameters:params
                            constructingBodyWithBlock:^(id <AFMultipartFormData> formData) {
                                
                                if (data.length > 0) {
                                    if ([name isEqualToString:@"photo_file"]) {
                                        [formData appendPartWithFileData:data
                                                                    name:name
                                                                fileName:@"rah.jpeg"
                                                                mimeType:@"image/jpeg"];
                                    } else {
                                        [formData appendPartWithFileData:data
                                                                    name:name
                                                                fileName:@"ss.mp4"
                                                                mimeType:@"video"];
                                    }
                                }
                            }];
        
        AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
        
        // if you want progress updates as it's uploading, uncomment the following:
        [operation setUploadProgressBlock:^(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite) {
            DLog(@"Sent %lld of %lld bytes", totalBytesWritten, totalBytesExpectedToWrite);
        }];
        
        [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
            if (enableDebugLog) {
                /* get URL string */
                NSString *urlString = operation.request.URL.absoluteString;
                
                /* check dict respone */
                DLog(@"Response for:%@\n==================\n%@==================", urlString, operation.responseString);
            }
            successBlock([operation.responseString JSONValue]);
        }                                failure:^(AFHTTPRequestOperation *operation, NSError *error) {
            NSString *errorMessage = error.localizedDescription;
            errorBlock(errorMessage);
        }];
        
        [networkEngine enqueueHTTPRequestOperation:operation];
    });
}

/*----------------------------------------------------------------------------
 Method: formRequestWithURLPath: params: filePath: successBlock: errorBlock: httpMethod:
 called a form request in SOAP type
 -----------------------------------------------------------------------------*/
- (void)formRequestWithURLPath:(NSString *)urlString
                        params:(NSMutableDictionary *)params
                         image:(UIImage *)image
                  successBlock:(void (^)(id))successBlock
                    errorBlock:(void (^)(NSString *))errorBlock
                 progressBlock:(void (^)(long long totalBytesWritten, long long totalBytesExpectedToWrite))progressBlock {
    
    if (!appDelegate.hasNetwork) {
        [NLUtils showAlertWithMessage:kNoConnectionErrorMessage];
        errorBlock(kNoConnectionErrorMessage);
        return;
    }
    
    DLog(@"url: %@", urlString);
    DLog("params:%@", [params JSONRepresentation]);
    
    NSData *data = UIImagePNGRepresentation(image);
    
    NSMutableURLRequest *request = [networkEngine multipartFormRequestWithMethod:@"POST"
                                                                            path:urlString
                                                                      parameters:params
                                                       constructingBodyWithBlock:^(id <AFMultipartFormData> formData) {
                                                           if (image && data.length > 0) {
                                                               [formData appendPartWithFileData:data name:@"file"
                                                                                       fileName:[params objectForKey:@"name"]
                                                                                       mimeType:@"image/jpeg"];
                                                           }
                                                       }];
    
    AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
    
    [operation setUploadProgressBlock:^(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite) {
        //NSLog(@"%d Sent %lld of %lld bytes",bytesWritten, totalBytesWritten, totalBytesExpectedToWrite);
        progressBlock(totalBytesWritten, totalBytesExpectedToWrite);
    }];
    
    [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
        if (enableDebugLog) {
            /* get URL string */
            NSString *urlString = operation.request.URL.absoluteString;
            
            /* check dict respone */
            DLog(@"Response for:%@\n==================\n%@==================", urlString, operation.responseString);
        }
        NSDictionary *response = [operation.responseString JSONValue];
        successBlock(response);
    }                                failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        NSString *errorMessage = error.localizedDescription;
        errorBlock(errorMessage);
        DLog(@"ERROR: %@", error);
    }];
    
    //continue upload when app go to background
    [operation setShouldExecuteAsBackgroundTaskWithExpirationHandler:^{
        // Handle iOS shutting you down (possibly make a note of where you
        // stopped so you can resume later)
    }];
}

/*----------------------------------------------------------------------------
 Method: formRequestWithURLPath: params: successBlock: errorBlock: httpMethod:
 called a form request in SOAP type
 -----------------------------------------------------------------------------*/
- (void)formRequestWithURLPath:(NSString *)urlString
                        params:(NSMutableDictionary *)params
                  successBlock:(void (^)(id))successBlock
                    errorBlock:(void (^)(NSString *))errorBlock {
    networkEngine.parameterEncoding = AFFormURLParameterEncoding;
    [self formRequestWithURLPath:urlString
                          params:params
                        filePath:nil
                            name:nil
                    successBlock:successBlock
                      errorBlock:errorBlock];
}
/* edit by Thong Vo Minh */
/*----------------------------------------------------------------------------
 Method: formRequestWithURLPath: params: successBlock: errorBlock: httpMethod:
 called a form request in SOAP type
 -----------------------------------------------------------------------------*/
-(void)cancelAllHTTPRequest{
    [[networkEngine operationQueue]cancelAllOperations];
}
@end
